/*!
 * \file WtDtRunner.cpp
 * \project	WonderTrader
 *
 * \author Wesley
 * \date 2020/03/30
 * 
 * \brief 数据运行器实现文件
 * 
 * \details 本文件实现了WonderTrader数据服务系统的数据运行器类WtDtRunner：
 *          - 负责数据服务系统的初始化和运行管理
 *          - 集成基础数据管理器和热点管理器
 *          - 提供数据查询的统一接口
 *          - 管理数据存储和数据管理器
 *          - 支持K线数据和Tick数据的查询服务
 *          - 实现数据服务的生命周期管理
 */
#include "WtDtRunner.h"
#include "../WtDtCore/WtHelper.h"

#include "../Includes/WTSSessionInfo.hpp"
#include "../Includes/WTSVariant.hpp"
#include "../WTSUtils/SignalHook.hpp"

#include "../WTSUtils/WTSCfgLoader.h"
#include "../WTSTools/WTSLogger.h"

/**
 * @brief 构造函数
 * @details 初始化数据运行器，设置初始状态并安装信号处理钩子
 */
WtDtRunner::WtDtRunner()
	: _data_store(NULL)
	, _is_inited(false)
{
#if _WIN32
// Signal hooks disabled in WIN32
#else
// Signal hooks enabled in UNIX
	// 在Unix系统下安装信号处理钩子，用于异常处理
	install_signal_hooks([](const char* message) {
		WTSLogger::error(message);
	});
#endif
}

/**
 * @brief 析构函数
 * @details 清理数据运行器资源
 */
WtDtRunner::~WtDtRunner()
{
}

/**
 * @brief 初始化数据运行器
 * @details 根据配置文件初始化数据服务系统，包括基础数据、热点数据和数据管理器
 * @param cfgFile 配置文件路径或配置字符串
 * @param isFile 是否为文件路径（true=文件路径，false=配置字符串）
 * @param modDir 模块目录路径
 */
void WtDtRunner::initialize(const char* cfgFile, bool isFile /* = true */, const char* modDir /* = "" */)
{
	if(_is_inited)
	{
		WTSLogger::error("WtDtServo has already been initialized");
		return;
	}

	// 初始化日志系统
	WTSLogger::init();
	WtHelper::set_module_dir(modDir);

	// 加载配置文件
	WTSVariant* config = isFile ? WTSCfgLoader::load_from_file(cfgFile, true) : WTSCfgLoader::load_from_content(cfgFile, false, true);
	if(config == NULL)
	{
		WTSLogger::error("Loading config failed");
		return;
	}

	// 加载基础数据文件
	WTSVariant* cfgBF = config->get("basefiles");
	bool isUTF8 = cfgBF->getBoolean("utf-8");
	
	// 加载交易时段配置
	if (cfgBF->get("session"))
	{
		_bd_mgr.loadSessions(cfgBF->getCString("session"), isUTF8);
		WTSLogger::info("Trading sessions loaded");
	}

	// 加载品种配置
	WTSVariant* cfgItem = cfgBF->get("commodity");
	if (cfgItem)
	{
		if (cfgItem->type() == WTSVariant::VT_String)
		{
			_bd_mgr.loadCommodities(cfgItem->asCString(), isUTF8);
		}
		else if (cfgItem->type() == WTSVariant::VT_Array)
		{
			for (uint32_t i = 0; i < cfgItem->size(); i++)
			{
				_bd_mgr.loadCommodities(cfgItem->get(i)->asCString(), isUTF8);
			}
		}
	}

	// 加载合约配置
	cfgItem = cfgBF->get("contract");
	if (cfgItem)
	{
		if (cfgItem->type() == WTSVariant::VT_String)
		{
			_bd_mgr.loadContracts(cfgItem->asCString(), isUTF8);
		}
		else if (cfgItem->type() == WTSVariant::VT_Array)
		{
			for (uint32_t i = 0; i < cfgItem->size(); i++)
			{
				_bd_mgr.loadContracts(cfgItem->get(i)->asCString(), isUTF8);
			}
		}
	}

	// 加载节假日配置
	if (cfgBF->get("holiday"))
	{
		_bd_mgr.loadHolidays(cfgBF->getCString("holiday"));
		WTSLogger::info("Holidays loaded");
	}

	// 加载主力合约规则
	if (cfgBF->get("hot"))
	{
		_hot_mgr.loadHots(cfgBF->getCString("hot"));
		WTSLogger::info("Hot rules loaded");
	}

	// 加载次主力合约规则
	if (cfgBF->get("second"))
	{
		_hot_mgr.loadSeconds(cfgBF->getCString("second"));
		WTSLogger::info("Second rules loaded");
	}

	// 初始化数据管理器
	initDataMgr(config->get("data"));

	config->release();

	_is_inited = true;
}

/**
 * @brief 初始化数据管理器
 * @details 根据配置初始化数据管理相关组件
 * @param config 配置参数
 */
void WtDtRunner::initDataMgr(WTSVariant* config)
{
	if (config == NULL)
		return;

	_data_mgr.init(config, this);

	WTSLogger::info("Data manager initialized");
}

/**
 * @brief 按时间范围获取K线数据
 * @details 根据指定的时间范围查询K线数据，支持周期字符串解析
 * @param stdCode 标准合约代码
 * @param period K线周期字符串（如"m1", "m5", "d1"等）
 * @param beginTime 开始时间（时间戳）
 * @param endTime 结束时间（时间戳，0表示到最新）
 * @return WTSKlineSlice* K线数据切片
 */
WTSKlineSlice* WtDtRunner::get_bars_by_range(const char* stdCode, const char* period, uint64_t beginTime, uint64_t endTime /* = 0 */)
{
	if(!_is_inited)
	{
		WTSLogger::error("WtDtServo not initialized");
		return NULL;
	}

	// 解析周期字符串，提取基础周期和倍数
	std::string basePeriod = "";
	uint32_t times = 1;
	if (strlen(period) > 1)
	{
		basePeriod.append(period, 1);
		times = strtoul(period + 1, NULL, 10);
	}
	else
	{
		basePeriod = period;
	}

	// 转换为内部周期枚举类型
	WTSKlinePeriod kp;
	uint32_t realTimes = times;
	if (strcmp(basePeriod.c_str(), "m") == 0)
	{
		// 分钟线处理，优化5分钟倍数的情况
		if (times % 5 == 0)
		{
			kp = KP_Minute5;
			realTimes /= 5;
		}
		else
		{
			kp = KP_Minute1;
		}
	}
	else
		kp = KP_DAY;

	// 如果结束时间为0，使用当前时间
	if (endTime == 0)
	{
		uint32_t curDate, curTime;
		TimeUtils::getDateTime(curDate, curTime);
		endTime = (uint64_t)curDate * 10000 + curTime/100000;
	}

	return _data_mgr.get_kline_slice_by_range(stdCode, kp, realTimes, beginTime, endTime);
}

/**
 * @brief 按时间范围获取Tick数据
 * @details 根据指定的时间范围查询Tick数据
 * @param stdCode 标准合约代码
 * @param beginTime 开始时间（时间戳）
 * @param endTime 结束时间（时间戳，0表示到最新）
 * @return WTSTickSlice* Tick数据切片
 */
WTSTickSlice* WtDtRunner::get_ticks_by_range(const char* stdCode, uint64_t beginTime, uint64_t endTime /* = 0 */)
{
	if (!_is_inited)
	{
		WTSLogger::error("WtDtServo not initialized");
		return NULL;
	}

	// 如果结束时间为0，使用当前时间
	if(endTime == 0)
	{
		uint32_t curDate, curTime;
		TimeUtils::getDateTime(curDate, curTime);
		endTime = (uint64_t)curDate * 10000 + curTime;
	}
	return _data_mgr.get_tick_slices_by_range(stdCode, beginTime, endTime);
}

/**
 * @brief 按数量获取K线数据
 * @details 从指定结束时间向前查询指定数量的K线数据，支持周期字符串解析
 * @param stdCode 标准合约代码
 * @param period K线周期字符串（如"m1", "m5", "d1"等）
 * @param count 查询数量
 * @param endTime 结束时间（时间戳，0表示最新）
 * @return WTSKlineSlice* K线数据切片
 */
WTSKlineSlice* WtDtRunner::get_bars_by_count(const char* stdCode, const char* period, uint32_t count, uint64_t endTime /* = 0 */)
{
	if (!_is_inited)
	{
		WTSLogger::error("WtDtServo not initialized");
		return NULL;
	}

	// 解析周期字符串，提取基础周期和倍数
	std::string basePeriod = "";
	uint32_t times = 1;
	if (strlen(period) > 1)
	{
		basePeriod.append(period, 1);
		times = strtoul(period + 1, NULL, 10);
	}
	else
	{
		basePeriod = period;
	}

	// 转换为内部周期枚举类型
	WTSKlinePeriod kp;
	uint32_t realTimes = times;
	if (strcmp(basePeriod.c_str(), "m") == 0)
	{
		// 分钟线处理，优化5分钟倍数的情况
		if (times % 5 == 0)
		{
			kp = KP_Minute5;
			realTimes /= 5;
		}
		else
		{
			kp = KP_Minute1;
		}
	}
	else
		kp = KP_DAY;

	// 如果结束时间为0，使用当前时间
	if (endTime == 0)
	{
		uint32_t curDate, curTime;
		TimeUtils::getDateTime(curDate, curTime);
		endTime = (uint64_t)curDate * 10000 + curTime / 100000;
	}

	return _data_mgr.get_kline_slice_by_count(stdCode, kp, realTimes, count, endTime);
}

/**
 * @brief 按数量获取Tick数据
 * @details 从指定结束时间向前查询指定数量的Tick数据
 * @param stdCode 标准合约代码
 * @param count 查询数量
 * @param endTime 结束时间（时间戳，0表示最新）
 * @return WTSTickSlice* Tick数据切片
 */
WTSTickSlice* WtDtRunner::get_ticks_by_count(const char* stdCode, uint32_t count, uint64_t endTime /* = 0 */)
{
	if (!_is_inited)
	{
		WTSLogger::error("WtDtServo not initialized");
		return NULL;
	}

	// 如果结束时间为0，使用当前时间
	if (endTime == 0)
	{
		uint32_t curDate, curTime;
		TimeUtils::getDateTime(curDate, curTime);
		endTime = (uint64_t)curDate * 10000 + curTime;
	}
	return _data_mgr.get_tick_slices_by_count(stdCode, count, endTime);
}